AWS Resource Access Manager (RAM) の共有先を SCP で制限する
いわさです。
先日、AWS Transit Gateway を組織内で共有した時に、SCP を使ってアタッチメント作成を行えないようにしてみました。
組織内共有されている Transit Gateway に対して、指定した OU から誤ってアタッチメント作成してしまうことを制限出来ると思います。
一方で Transit Gateway に限らず、そもそも組織内共有の共有先をもう少し制限出来ないものかと思ったりもします。
今回は前回の延長で、RAM で共有を行う際に SCP で共有先を制限出来ないか試してみたいと思います。
前提の確認
前回の記事でも触れられていますが、RAM でリソース共有を作成するとCreateResourceShare
アクションが実行されます。
今回はリソース共有作成を制限したいので、このアクションを SCP で制限してみたいと思います。
上記からCreateResourceShare
アクションで利用できる条件キーは以下のあたりです。
- aws:RequestTag/${TagKey}
- aws:TagKeys
- ram:RequestedResourceType
- ram:ResourceArn
- ram:RequestedAllowsExternalPrincipals
- ram:Principal
ram:RequestedResourceType
とram:ResourceArn
はリソース共有作成時に指定するリソースに関してですね。
例えば「RAM の組織共有は有効化したいけども特定のリソースタイプのみに限りたい」という設定をしたい時に使えそうです。
そして、ram:RequestedAllowsExternalPrincipals
とram:Principal
は共有先に関する条件に使えそうです。
ということで今回は上記2つのキーに関して評価して、SCP で使ってみます。
外部との共有を制限する
まずはram:RequestedAllowsExternalPrincipals
です。
こちらは非常にイメージしやすいのですが、リソース共有作成時の以下設定値に関するものになります。
「すべてのユーザーとの共有を許可」では組織外の AWS アカウント ID などを指定して共有が可能です。
「自分の組織内でのみ共有を許可」では組織外の AWS アカウント ID などの指定ができなくなります。
組織内共有は OK だけど、組織外との共有を制限したいということはよくありそうです。ram:RequestedAllowsExternalPrincipals
で制限してみましょう。
次のような SCP を作成して OU にアタッチしました。
「すべてのユーザーとの共有を許可」を「はい」にするとリソース共有の作成に失敗するようになりました。
「自分の組織内でのみ共有を許可」の場合は成功します。
ただし、「すべてのユーザーとの共有を許可」を「はい」にすると組織内の AWS アカウントや OU を指定した場合でもエラーになります。
この条件キーは「外部プリンシパルを許可」の値のみがチェック対象ですので注意しましょう。
プリンシパルを制限する
組織外共有の制限が出来そうだということで、続いては組織内の共有先制限も出来るか見てみましょう。
今度はram:Principal
が使えそうです。
ただし、厄介なことにこの共有先として指定するプリンシパルは色々なタイプがあります。
当然ですがそれぞれのプリンシパルタイプに対してそもそも許可するのかしないのかの要件を事前に整理しておく必要があります。
どのプリンシパルタイプでも ARN、AWS アカウント ID、サービスプリンシパルの文字列をram:Principal
でフィルタリングする形になります。
参考までにそれぞれのプリンシパルタイプを指定した時の CloudTrail イベントレコードの情報を調べたので記載しておきます。
アカウントを指定した場合
"requestParameters": {
"name": "hoge0113share2ouc",
"resourceArns": [],
"principals": [
"111122223333"
],
"permissionArns": [],
"allowExternalPrincipals": false,
"tags": []
},
組織 ID を指定した場合
"requestParameters": {
"name": "hoge0113share2",
"resourceArns": [],
"principals": [
"arn:aws:organizations::123456789012:organization/o-8j81brsjuj"
],
"permissionArns": [],
"allowExternalPrincipals": false,
"tags": []
},
任意の OU A を指定した場合
"requestParameters": {
"name": "hoge0113ouc",
"resourceArns": [],
"principals": [
"arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-o3k5ritj"
],
"permissionArns": [],
"allowExternalPrincipals": false,
"tags": []
},
OU-A の子 OU である、OU B を指定した場合
"requestParameters": {
"name": "hoge0113child",
"resourceArns": [],
"principals": [
"arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-i8dknce4"
],
"permissionArns": [],
"allowExternalPrincipals": false,
"tags": []
},
IAM ユーザーを指定した場合
"requestParameters": {
"name": "hoge0113shareservice",
"resourceArns": [],
"principals": [
"arn:aws:iam::123456789012:user/hoge"
],
"permissionArns": [],
"allowExternalPrincipals": false,
"tags": []
},
試しに特定 OU を拒否してみますか。次のような SCP を作成してアタッチしました。
良いですね。指定した OU に対するリソース共有を作成しようとしたところエラーとなりました。
一方で、OU の ARN は階層構造になっているわけではないので禁止された OU の下層にある OU であれば許可出来たりします。
あとはアカウント ID や組織 ID の指定も可能です。そうなってくるとブラックリスト形式での指定は非常に大変そうです。
特定の OU のみ許可するような、次のようなホワイトリスト形式のほうが良さそうかなという感じがします。
まとめたポリシーを作成する
さらにまだいくつか考慮しなければいけないこともあります。
リソース共有は変更が可能です。外部共有の ON/OFF 設定を変更したり、共有先プリンシパルの追加が可能です。
この時どうなるかというと、リソース共有に対して共有プリンシパルを追加したり、あるいは対象リソースを追加する時にはram:AssociateResourceShare
が発生します。
リソース共有は共有プリンシパルやリソースの指定はせずにとりあえず作成だけして、後から共有プリンシパルやリソースを追加する使い方をするのが多いです。なのでram:AssociateResourceShare
アクションは無視できません。
ただ、調べたところram:AssociateResourceShare
もram:Principal
条件キーは使用可能です。やったね。
また、外部共有の ON/OFF 変更など、リソースやプリンシパルの追加以外のリソース共有自体の設定変更についてはram:UpdateResourceShare
が発生しました。
こちらもram:RequestedAllowsExternalPrincipals
条件キーが使用可能です。
以上をまとめるとこんな感じになると思います。
SCP はアタッチ出来る上限数があるので[1]、ひとつにまとめてみます。
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Statement1",
"Effect": "Deny",
"Action": [
"ram:CreateResourceShare",
"ram:AssociateResourceShare"
],
"Resource": "*",
"Condition": {
"StringNotEquals": {
"ram:Principal": [
"arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-i056l45b",
"arn:aws:organizations::123456789012:ou/o-8j81brsjuj/ou-s4h9-ofgjiapb"
]
},
"Null": {
"ram:Principal": false
}
}
},
{
"Sid": "Statement2",
"Effect": "Deny",
"Action": [
"ram:CreateResourceShare",
"ram:UpdateResourceShare"
],
"Resource": "*",
"Condition": {
"Bool": {
"ram:RequestedAllowsExternalPrincipals": "true"
}
}
}
]
}
ram:CreateResourceShare
はリソース共有作成時にプリンシパルを指定しない場合があったり、ram:AssociateResourceShare
ではプリンシパルではなくリソースイベントが入ってくることがあります。
そのため指定しなかった場合に Deny が起きないように Null 条件を指定しています。[2]
動作確認してみましょう。
まずプリンシパルやリソースを指定せずに内部共有可能なリソース共有を作成することができました。
これを外部共有可能に設定しようとするとエラーが発生しました。
さらに、許可されていない OU をプリンシパルに指定しようとするとエラーになりました。
そして、許可されている OU であればプリンシパルへの追加ができました。
期待どおり動作していそうですね。
さいごに
本日はAWS Resource Access Manager (RAM) の共有先を SCP で制限してみました。
なかなか良いのではないでしょうか。
デフォルトだと RAM の組織利用が有効化されると、結構オープンに共有可能になってしまうので SCP によるリソース共有の制限は使えそうです。